package com.zzcoder.mall.common.config;

import com.zzcoder.mall.data.dao.repository.*;
import com.zzcoder.mall.data.model.*;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

@Component
public class InitializeData {
    private final String[] productNames = new String[]{
            "无印良品 MUJI 基础润肤化妆水",
            "无印良品 MUJI 柔和洁面泡沫",
            "无印良品 MUJI 男式','无侧缝法兰绒 睡衣 海军蓝",
            "无印良品 MUJI 男式','干爽 凉感珠地网眼编织V领短袖T恤 黑色 L",
            "小米 Redmi AirDots",
            "荣耀原装三键线控带麦半入耳式耳机AM116(尊爵版)适用于华为荣耀手机",
            "华为耳机原装半入耳式有线mate9p10plus8x荣耀v20v10nova2s9iv9p9play 【标准版】华为AM115 白色-热卖款",
            "Beats X 蓝牙无线','入耳式耳机 带麦可通话 -桀骜黑红（十周年版） MRQA2PA/A",
            "海囤全球 汤姆福特 TOM",
            "美宝莲（MAYBELLINE）绝色持久唇膏雾感哑光系列R09PM 3.9g（女皇色口红新老包装）",
            "【专柜正品】迪奥999Dior口红唇膏烈艳蓝金 哑光滋润520/888/999送礼礼品套装 烈艳蓝金"
    };
    private Random random = new Random();
    private UmsAdminRepository adminRepository;
    private PasswordEncoder passwordEncoder;
    private UmsMemberRepository memberRepository;
    private PmsCategoryRepository categoryRepository;
    private PmsProductRepository productRepository;
    private OmsOrderRepository orderRepository;
    private OmsOrderItemRepository orderItemRepository;
    private UmsAddressRepository addressRepository;
    private OmsCartItemRepository cartItemRepository;
    private SmsCarouselRepository carouselRepository;
    private SmsNewProductRepository newProductRepository;
    private SmsHotProductRepository hotProductRepository;

    public InitializeData(
            UmsAdminRepository adminRepository,
            PasswordEncoder passwordEncoder,
            UmsMemberRepository memberRepository,
            PmsCategoryRepository categoryRepository,
            PmsProductRepository productRepository,
            OmsOrderRepository orderRepository,
            OmsOrderItemRepository orderItemRepository,
            UmsAddressRepository addressRepository,
            OmsCartItemRepository cartItemRepository,
            SmsCarouselRepository carouselRepository,
            SmsNewProductRepository newProductRepository,
            SmsHotProductRepository hotProductRepository
    ) {
        this.adminRepository = adminRepository;
        this.passwordEncoder = passwordEncoder;
        this.memberRepository = memberRepository;
        this.categoryRepository = categoryRepository;
        this.productRepository = productRepository;
        this.orderRepository = orderRepository;
        this.orderItemRepository = orderItemRepository;
        this.addressRepository = addressRepository;
        this.cartItemRepository = cartItemRepository;
        this.carouselRepository = carouselRepository;
        this.newProductRepository = newProductRepository;
        this.hotProductRepository = hotProductRepository;
    }

    public void execute() throws ParseException {
        UmsAdmin admin = new UmsAdmin();
        admin.setUsername("admin");
        admin.setPassword(passwordEncoder.encode("aaaaaa"));
        admin.setAvatarUrl("/api/v1.0/file-storage/avatar/default.png");
        admin = adminRepository.save(admin);

        for (int i = 1; i < random.nextInt(10); i++) {
            UmsAdmin a = new UmsAdmin();
            a.setUsername("admin" + (i + 1));
            a.setPassword(passwordEncoder.encode("aaaaaa"));
            a.setAvatarUrl("/api/v1.0/file-storage/avatar/default.png");
            a = adminRepository.save(a);
        }

        List<UmsMember> members = new ArrayList<>();
        for (int i = 0; i < random.nextInt(41) + 10; i++) {
            UmsMember m = new UmsMember();
            m.setUsername("m" + (i + 1));
            m.setNickname("mn" + (i + 1));
            m.setPassword(passwordEncoder.encode("aaaaaa"));
            m.setAvatarUrl("/api/v1.0/file-storage/avatar/default.png");
            m = memberRepository.save(m);
            members.add(m);

            List<UmsAddress> addresses = new ArrayList<>();
            for (int j = 0; j < random.nextInt(6); j++) {
                UmsAddress address = new UmsAddress();
                address.setMemberId(m.getId());
                address.setReceiverName("receiver" + i);
                address.setReceiverPhone("13163444414");
                address.setReceiverProvinceCode("320000");
                address.setReceiverProvince("江苏省");
                address.setReceiverCityCode("320100");
                address.setReceiverCity("南京市");
                address.setReceiverDistrictCode("320113");
                address.setReceiverDistrict("栖霞区");
                address.setReceiverAddress("仙林大学城文苑路10" + i + "号xxxx大学");

                address = addressRepository.save(address);
                addresses.add(address);
            }
            if (addresses.size() > 0) {
                UmsAddress defaultAddress = addresses.get(random.nextInt(addresses.size()));
                defaultAddress = addressRepository.save(defaultAddress);
            }
        }

        List<PmsCategory> categories = new ArrayList<>();
        for (int i = 0; i < random.nextInt(21) + 20; i++) {
            PmsCategory c = new PmsCategory();
            c.setName("c" + (i + 1));
            PmsCategory parent = null;
            if (random.nextBoolean() && categories.size() > 0) {
                parent = categories.get(random.nextInt(categories.size()));
                c.setParentId(parent.getId());
            }
            c = categoryRepository.save(c);

            if (c.getParentId() == null) {
                c.setRootId(c.getId());
                c.setLevel(0);
            } else {
                c.setParentId(parent.getId());
                c.setRootId(parent.getRootId());
                c.setLevel(parent.getLevel() + 1);
            }
            c = categoryRepository.save(c);
            categories.add(c);
        }

        List<PmsProduct> products = new ArrayList<>();
        for (int i = 0; i < random.nextInt(41) + 10; i++) {
            PmsProduct p = new PmsProduct();
            p.setName(productNames[random.nextInt(productNames.length)] + (i + 1));
            p.setSummary("summary p" + (i + 1));
            p.setDetail("<p>detail p" + (i + 1) + "</p><p>商品信息加载中</p>");
            p.setImgUrl("/api/v1.0/file-storage/product/sample" + (random.nextInt(7) + 1) + ".jpg");
            p.setStock((long) random.nextInt(101));
            p.setPrice((long) random.nextInt(10001) / 100.0);
            p.setSellingStatus(random.nextBoolean() ? PmsSellingStatus.PUT_ON_SHELVES : PmsSellingStatus.PULL_OFF_SHELVES);
            p.setCategoryId(categories.get(random.nextInt(categories.size())).getId());

            p = productRepository.save(p);
            products.add(p);
        }

        List<SmsCarousel> carousels = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            SmsCarousel carousel = new SmsCarousel();
            carousel.setImgUrl("/api/v1.0/file-storage/carousel/carousel" + (random.nextInt(3) + 1) + ".png");
            carousel.setLinkType(SmsLinkType.values()[random.nextInt(SmsLinkType.values().length)]);
            if (carousel.getLinkType().equals(SmsLinkType.LINK)) {
                carousel.setLinkUrl("https://www.baidu.com");
            } else if (carousel.getLinkType().equals(SmsLinkType.PRODUCT)) {
                PmsProduct p = products.get(random.nextInt(products.size()));
                carousel.setProductId(p.getId());
                carousel.setProductName(p.getName());
                carousel.setProductImgUrl(p.getImgUrl());
            }
            carousel.setDisplay(random.nextBoolean());

            carousel = carouselRepository.save(carousel);
            carousels.add(carousel);
        }

        List<SmsNewProduct> newProducts = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            SmsNewProduct newProduct = new SmsNewProduct();
            newProduct.setRank(random.nextInt(100));
            PmsProduct p = products.get(random.nextInt(products.size()));
            newProduct.setProductId(p.getId());
            newProduct.setProductName(p.getName());
            newProduct.setProductImgUrl(p.getImgUrl());

            newProduct = newProductRepository.save(newProduct);
            newProducts.add(newProduct);
        }

        List<SmsHotProduct> hotProducts = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            SmsHotProduct hotProduct = new SmsHotProduct();
            hotProduct.setRank(random.nextInt(100));
            PmsProduct p = products.get(random.nextInt(products.size()));
            hotProduct.setProductId(p.getId());
            hotProduct.setProductName(p.getName());
            hotProduct.setProductImgUrl(p.getImgUrl());

            hotProduct = hotProductRepository.save(hotProduct);
            hotProducts.add(hotProduct);
        }

        List<OmsCartItem> cartItems = new ArrayList<>();
        for (int i = 0; i < 1; i++) {
            OmsCartItem cartItem = new OmsCartItem();
            cartItem.setMemberId(members.get(0).getId());
            PmsProduct p = products.get(random.nextInt(products.size()));
            cartItem.setProductId(p.getId());
            cartItem.setProductName(p.getName());
            cartItem.setProductImgUrl(p.getImgUrl());
            cartItem.setQuantity(random.nextInt(5) + 1L);
            cartItem.setPrice(p.getPrice());

            cartItem = cartItemRepository.save(cartItem);
            cartItems.add(cartItem);
        }
        for (int i = 0; i < random.nextInt(41) + 10; i++) {
            OmsCartItem cartItem = new OmsCartItem();
            cartItem.setMemberId(members.get(random.nextInt(members.size() - 1) + 1).getId());
            PmsProduct p = products.get(random.nextInt(products.size()));
            cartItem.setProductId(p.getId());
            cartItem.setProductName(p.getName());
            cartItem.setProductImgUrl(p.getImgUrl());
            cartItem.setQuantity(random.nextInt(5) + 1L);
            cartItem.setPrice(p.getPrice());

            cartItem = cartItemRepository.save(cartItem);
            cartItems.add(cartItem);
        }

        List<OmsOrder> orders = new ArrayList<>();
        for (int i = 0; i < random.nextInt(41) + 30; i++) {
            OmsOrder order = new OmsOrder();
            order.setOrderStatus(OmsOrderStatus.values()[random.nextInt(OmsOrderStatus.values().length)]);
            UmsMember m = members.get(random.nextInt(members.size()));
            order.setMemberId(m.getId());
            order.setMemberNickname(m.getNickname());
            order.setAmount((long) random.nextInt(10001) / 100.0);
            order.setReceiverName("receiver" + i);
            order.setReceiverPhone("13163444414");
            order.setReceiverProvinceCode("320000");
            order.setReceiverProvince("江苏省");
            order.setReceiverCityCode("320100");
            order.setReceiverCity("南京市");
            order.setReceiverDistrictCode("320113");
            order.setReceiverDistrict("栖霞区");
            order.setReceiverAddress("仙林大学城文苑路10" + i + "号xxxx大学");

            DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            Date start = dateFormat.parse("20180101");
            Date end = dateFormat.parse("20220625");
            Date orderTime = randomDate(start, end);
            order.setOrderTime(orderTime);
            order.setCode("XSDD" + dateFormat.format(orderTime) + String.format("%06d", i + 1));
            if (order.getOrderStatus().equals(OmsOrderStatus.CLOSED)) {
                order.setClosedTime(randomDate(orderTime, end));
            } else {
                Date paymentTime = randomDate(orderTime, end);
                if (order.getOrderStatus().ordinal() >= OmsOrderStatus.UN_EXPRESSED.ordinal()) {
                    order.setPaymentTime(paymentTime);
                    order.setPaymentType(OmsPaymentType.values()[random.nextInt(2) + 1]);
                    order.setPaymentAccount(order.getPaymentType().name() + i);
                }
                Date expressTime = randomDate(paymentTime, end);
                if (order.getOrderStatus().ordinal() >= OmsOrderStatus.EXPRESSED.ordinal()) {
                    order.setExpressTime(expressTime);
                    order.setExpressCompany("Express Company" + i);
                    order.setExpressNumber("Express" + i);
                }
                Date receivedTime = randomDate(expressTime, end);
                if (order.getOrderStatus().ordinal() >= OmsOrderStatus.RECEIVED.ordinal()) {
                    order.setReceivedTime(receivedTime);
                }
                Date confirmTime = randomDate(receivedTime, end);
                if (order.getOrderStatus().ordinal() >= OmsOrderStatus.COMPLETE.ordinal()) {
                    order.setConfirmTime(confirmTime);
                }
            }

            order = orderRepository.save(order);
            orders.add(order);

            for (int j = 0; j < random.nextInt(5) + 1; j++) {
                OmsOrderItem item = new OmsOrderItem();
                item.setOrderId(order.getId());
                PmsProduct p = products.get(random.nextInt(products.size()));
                item.setProductId(p.getId());
                item.setProductName(p.getName());
                item.setProductImgUrl(p.getImgUrl());
                item.setQuantity((long) random.nextInt(10) + 1);
                item.setPrice(p.getPrice());

                item = orderItemRepository.save(item);
            }

        }
    }

    private Date randomDate(Date start, Date end) {
        try {
            //getTime()表示返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
            if (start.getTime() >= end.getTime()) {
                return null;
            }

            long date = random(start.getTime(), end.getTime());
            return new Date(date);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private long random(long begin, long end) {
        long rtn = begin + (long) (Math.random() / 2.0 * (end - begin));
        //如果返回的是开始时间和结束时间，则递归调用本函数查找随机值
        if (rtn == begin || rtn == end) {
            return random(begin, end);
        }
        return rtn;
    }
}
